package root.historic;

import java.security.InvalidParameterException;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

import root.historic.componenteLog.Amizade;
import root.historic.componenteLog.ComponenteLog;
import root.historic.componenteLog.EmprestimoAprovado;
import root.historic.componenteLog.InteressePeloItem;
import root.historic.componenteLog.ItemCadastrado;
import root.historic.componenteLog.PublicarPedido;
import root.historic.componenteLog.TerminoDeEmprestimo;
import root.historic.event.AmizadeEvent;
import root.historic.event.EmprestimoEvent;
import root.historic.event.InteressePeloItemEvent;
import root.historic.event.ItemEvent;
import root.item.ItemListener;
import root.item.ItemOferecidoEvent;
import root.item.PublicarPedidoEvent;
import root.loan.EmprestimoListener;
import root.user.User;

public class Historic implements EmprestimoListener, AmizadeListener,ItemListener {
	
	private LinkedList<ComponenteLog> logs;
	private LinkedList<ComponenteLog> logsCompartilhados;
	User user;
	public Historic(User user) {
		logs = new LinkedList<ComponenteLog>();
		logsCompartilhados = new LinkedList<ComponenteLog>();
		this.user = user;
	}
	private void addLog(ComponenteLog log) {
		if(log==null){
			throw new InvalidParameterException("Log Invalido");
		}
		if(logs.contains(log)) logs.remove(log);
		logs.addFirst(log);
		addLogCompratilhados(log);
	}
	
	private void addLogCompratilhados(ComponenteLog log){
		if(log==null){
			throw new InvalidParameterException("Log Invalido");
		}
		if(!logsCompartilhados.contains(log))
			logsCompartilhados.addFirst(log);
	}
	
	private void addAllLogCompratilhados(Collection<ComponenteLog> colecao){
		
		LinkedList<ComponenteLog> novoLog = new LinkedList<ComponenteLog>();
		
		Iterator<ComponenteLog> it = colecao.iterator();
		Iterator<ComponenteLog> it2 = logsCompartilhados.iterator();
		
		ComponenteLog proximo = null;
		boolean variou = false;
		boolean variou2 = false;
		ComponenteLog next = null;
		ComponenteLog next2 = null;
		
		while(it.hasNext() && it2.hasNext()){
			next = variou ? next : it.next();
			next2 = variou2 ? next2 : it2.next();
			
			proximo = next2.compareTo(next) < 0 ? next : next2;  
			variou = next2.compareTo(next) < 0 ? true : false;
			variou2 = next2.compareTo(next) < 0 ? false : true;
			
			if(!novoLog.contains(proximo))
				novoLog.addLast(proximo);
			
			variou = false;
			variou2 = false;
		}
		
		while(it.hasNext()){
			proximo = it.next();
			if(!novoLog.contains(proximo))
				novoLog.addLast(proximo);
		}
		while(it2.hasNext()){
			proximo = it2.next();
			if(!novoLog.contains(proximo))
				novoLog.addLast(proximo);
		}
		
		logsCompartilhados = novoLog;
	}
	private String preparaMsg(Collection<ComponenteLog> lista){
		String resp = "";
		Iterator<ComponenteLog> it = lista.iterator();
		while(it.hasNext()){
			resp = resp.concat(it.next()+"; ");
		}
		if(resp.endsWith("; ")){
			resp = resp.substring(0, resp.length()-2);
		}
		if(resp.isEmpty()){
			resp = "Não há atividades";
		}
		return resp;
	}
	
	
	public String getHistorico(){
		return preparaMsg(logs);
	}
	
	public String getHistoricoAtividadesConjunto(){
		return preparaMsg(logsCompartilhados);
	}
	
	@Override
	public void notifyAmizadeAprovada(AmizadeEvent event) {
		String primeiroNome = event.getUserAprovadorName();
		String segundoNome = event.getUserAprovadoName();
		
		ComponenteLog log = new Amizade(primeiroNome,segundoNome);
		
		if(event.getSource().equals(user)){
			addLog(log);
			addAllLogCompratilhados(event.getUserAprovado().getHistoric().logs);
		} else {
			addLogCompratilhados(log);
		}
	}
	
	@Override
	public void notifyItemCadastrado(ItemEvent event) {
		ComponenteLog log = new ItemCadastrado(event.getDono().getName(),event.getNomeItem());
		if(event.getDono().equals(user)){
			addLog(log);
		} else {
			addLogCompratilhados(log);
		} 
	}

	@Override
	public void notifyEmprestimoAprovado(EmprestimoEvent event) {
		ComponenteLog log = new EmprestimoAprovado(event.getDono().getName(),event.getNomeItem(),event.getNomeBeneficiadoItem());
		if(event.getDono().equals(user)){
			addLog(log);
		} else {
			addLogCompratilhados(log);
		}
	}

	@Override
	public void notifyInteressePeloItem(InteressePeloItemEvent event) {
		
		ComponenteLog log = new InteressePeloItem(event.getInteressadoItem().getName(),event.getNomeItem()
				,event.getNomeDonoItem());
		if(event.getInteressadoItem().equals(user)){
			addLog(log);
		} else {
			addLogCompratilhados(log);
		}
	}

	@Override
	public void notifyTerminoDeEmprestimo(EmprestimoEvent event) {
		ComponenteLog log = new TerminoDeEmprestimo(event.getDono().getName(),event.getNomeItem());
		if(event.getDono().equals(user)){
			addLog(log);
		} else {
			addLogCompratilhados(log);
		}
		
	}

	@Override
	public void itemDevolvido(ItemEvent arg0) {
		// Eu quero la saber se o item foi devolvido
		// lascar oto
	}
	@Override
	public void notifyPublicarPedido(PublicarPedidoEvent event) {
		ComponenteLog log = new PublicarPedido(event.getDono().getName(),event.getNomeItem());
		if(event.getDono().equals(user)){
			addLog(log);
		} else {
			addLogCompratilhados(log);
		}
	}
	@Override
	public void notifyRequisitarEmprestimo(EmprestimoEvent event) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void notifyRequisicaoDeDevolucao(EmprestimoEvent event) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void notifyOfereceuItem(ItemOferecidoEvent event) {
		// TODO Auto-generated method stub
		
	}


}
